package com.nanbei.queue;


import java.util.Iterator;

/**
 * @ClassDescription: 单向环形带哨兵的链表方式来实现队列
 * @JdkVersion: 17
 * @Author: BaoShan.li
 * @Created: 2023/11/23 10:11
 */
public class LinkQueue<E> implements QueueInterface<E>, Iterable<E> {


    /**
     * 定义链表节点
     *
     * @param <E> 泛型
     */
    private static class Node<E> {
        E value;
        Node<E> next;

        public Node(E value, Node<E> next) {
            this.value = value;
            this.next = next;
        }
    }

    //创建一个哨兵节点、一个头指针、一个尾指针。让头尾指针都指向哨兵节点。
    Node<E> sentinel = new Node<E>(null, null);
    Node<E> head = sentinel;
    Node<E> tail = sentinel;

    private int size = 0;
    private int capacity = Integer.MAX_VALUE;

    {
        //在两个构造函数中都使用了该赋值语句所以将它提取出来
        //刚开始没有数据的时候让哨兵的下一个节点指向自己
        sentinel.next = sentinel;
    }

    public LinkQueue() {

    }

    public LinkQueue(int capacity) {
        this.capacity = capacity;
    }

    @Override
    public boolean offer(E value) {

        if (isFull()) {
            return false;
        }

        Node<E> eNode = new Node<>(value, sentinel);
        tail.next = eNode;
        tail = eNode;

        size++;

        return true;
    }

    @Override
    public E poll() {
        if (isEmpty()) {
            return null;
        }
        E value = head.next.value;
        head.next = head.next.next;

        size--;
        return value;
    }

    @Override
    public E peek() {
        if (isEmpty()) {
            return null;
        }
        return head.next.value;
    }

    @Override
    public boolean isEmpty() {
        return head == tail;
    }

    @Override
    public boolean isFull() {
        return capacity == size;
    }

    @Override
    public Iterator<E> iterator() {
        return new Iterator<E>() {

            Node<E> node = head.next;

            @Override
            public boolean hasNext() {

                return node != head;
            }

            @Override
            public E next() {
                E value = node.value;
                node = node.next;
                return value;
            }
        };
    }
}
